package com.fine.hair.comm.exception;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.fine.hair.comm.utils.ApiResponse;
import com.fine.hair.comm.utils.BaseException;
import com.fine.hair.comm.utils.MyStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolationException;


/**
 * <p>
 * 全局统一异常处理
 * </p>
 *
 * ControllerAdvice 该注解决定是否打开全局异常处理
 *
 * @description: 全局统一异常处理
 */
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ApiResponse handlerException(Exception e) {
        if (e instanceof NoHandlerFoundException) {
            log.error("【全局异常拦截】NoHandlerFoundException: 请求方法 {}, 请求路径 {}", ((NoHandlerFoundException) e).getRequestURL(), ((NoHandlerFoundException) e).getHttpMethod());
            return ApiResponse.ofStatus(MyStatus.REQUEST_NOT_FOUND);
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            log.error("【全局异常拦截】HttpRequestMethodNotSupportedException: 当前请求方式 {}, 支持请求方式 {}", ((HttpRequestMethodNotSupportedException) e).getMethod(), JSONUtil.toJsonStr(((HttpRequestMethodNotSupportedException) e).getSupportedHttpMethods()));
            return ApiResponse.ofStatus(MyStatus.HTTP_BAD_METHOD);
        } else if (e instanceof MethodArgumentNotValidException) {
            log.error("【全局异常拦截】MethodArgumentNotValidException", e);
            return ApiResponse.of(MyStatus.BAD_REQUEST.getCode(), ((MethodArgumentNotValidException) e).getBindingResult()
                    .getAllErrors()
                    .get(0)
                    .getDefaultMessage(), null);
        } else if (e instanceof ConstraintViolationException) {
            log.error("【全局异常拦截】ConstraintViolationException", e);
            return ApiResponse.of(MyStatus.BAD_REQUEST.getCode(), CollUtil.getFirst(((ConstraintViolationException) e).getConstraintViolations())
                    .getMessage(), null);
        } else if (e instanceof MethodArgumentTypeMismatchException) {
            log.error("【全局异常拦截】MethodArgumentTypeMismatchException: 参数名 {}, 异常信息 {}", ((MethodArgumentTypeMismatchException) e).getName(), ((MethodArgumentTypeMismatchException) e).getMessage());
            return ApiResponse.ofStatus(MyStatus.PARAM_NOT_MATCH);
        } else if (e instanceof HttpMessageNotReadableException) {
            log.error("【全局异常拦截】HttpMessageNotReadableException: 错误信息 {}", ((HttpMessageNotReadableException) e).getMessage());
            return ApiResponse.ofStatus(MyStatus.PARAM_NOT_NULL);
        }
        else if (e instanceof BaseException) {
            e.printStackTrace();
            log.error("【全局异常拦截】BaseException: 状态码 {}, 异常信息 {}", ((BaseException) e).getCode(), e.getMessage());
            return ApiResponse.ofException((BaseException) e);
        } else if (e instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException mpe = (MissingServletRequestParameterException) e;
            log.error("【全局异常拦截】: 缺失参数: {}", mpe.getParameterName());
            BaseException exception = new BaseException(MyStatus.BAD_REQUEST.getCode(),
                    "必要参数 '" + mpe.getParameterName() + "' 缺失");
            return ApiResponse.ofError(exception);
        } else if (e instanceof BusinessException) {
            e.printStackTrace();
            log.error("【全局异常拦截】: BusinessException 业务异常 {} ", e.getMessage());
            return ApiResponse.ofError(e);
        }else if (e instanceof java.lang.SecurityException) {
            e.printStackTrace();
            log.error("【全局异常拦截】SecurityException: 异常信息 {}", e.getMessage());
            return ApiResponse.ofException((BaseException) e);
        }
        e.printStackTrace();
        log.error("【全局异常拦截】: 异常信息 {} ", e.getMessage());
        return ApiResponse.ofStatus(MyStatus.ERROR);
    }

}
